package controller

import (
	"encoding/json"
	"fmt"
	"htmlcopy/core"
	"io/ioutil"
	"net/http"
	"regexp"

	"golang.org/x/net/websocket"
)

var maxsearch chan int = make(chan int, 1)

type ResultJson struct {
	Status  int64             `json:"code"`
	Message string            `json:"message"`
	Cr      core.CopyerResult `json:"data"`
}

// 用于ajax提交抓取请求
func SearchAjax(w http.ResponseWriter, r *http.Request) {
	// 创建返回json容器
	rt := ResultJson{}

	// 限制同时运行的抓取请求
	select {
	case maxsearch <- 1:
		defer func() {
			<-maxsearch
		}()
	default:
		rt.Status = 1
		rt.Message = "服务器抓取队列过多，请稍后再试"
		j, _ := json.Marshal(&rt)
		w.Write(j)
		return
	}

	// 参数验证
	url := r.FormValue("url")
	reg := regexp.MustCompile(`^http.*`)
	if v := reg.FindString(url); v == "" {
		rt.Status = 1
		rt.Message = "这不是一个有效的 <strong>URL</strong> 地址，请重新输入"
		j, _ := json.Marshal(&rt)
		w.Write(j)
		return
	}

	// 调取服务进行抓取工作
	qiniu := core.NewQiniu()
	coper := core.NewCoper(qiniu, qiniu, qiniu, qiniu)
	cr, err := core.Copy(url, coper)
	if err != nil {
		rt.Message = err.Error()
		rt.Status = 1
		j, _ := json.Marshal(&rt)
		w.Write(j)
		return
	}

	w.Header().Add("Content-Type", "application/json; charset=utf-8")
	rt.Status = 0
	rt.Cr = cr
	j, err := json.Marshal(&rt)
	w.Write(j)
}

// 用于websocket提交的抓取请求
func SearchSocket(ws *websocket.Conn) {
	fmt.Printf("--> sendRecvServer %#v\n", ws)
	for {
		// 接收websocket传递的信息
		var buf string
		err := websocket.Message.Receive(ws, &buf)
		if err != nil {
			fmt.Println(err)
			break
		}
		reg := regexp.MustCompile(`^http.*`)
		if v := reg.FindString(buf); v == "" {
			_, err = ws.Write([]byte("这不是一个有效的URL地址，请重新输入 end"))
			if err != nil {
				fmt.Println(err)
				break
			}
			continue
		}

		// 限制同时运行的抓取请求
		select {
		case maxsearch <- 1:
			ws.Write([]byte("server start..."))
		default:
			ws.Write([]byte("服务器抓取队列过多，请稍后再试 end"))
			continue
		}

		// 开始调用服务进行页面抓取, 并实时回写抓取信息
		qiniu := core.NewQiniu()
		coper := core.NewCoper(qiniu, qiniu, qiniu, ws)
		cr, err := core.Copy(buf, coper)

		// 验证错误信息，并回写到客户端
		if err != nil {
			ws.Write([]byte(err.Error() + " end"))
			<-maxsearch // 完成本次抓取操作，释放占用的链接数量
			continue
		}

		// 输出结果信息到客户端
		ws.Write([]byte("|------ 解析抓取结束，以下为结果信息 ------|"))
		ws.Write([]byte("|-- 下载失败资源列表:"))
		for _, v := range cr.DE {
			ws.Write([]byte(v))
		}
		ws.Write([]byte("|-- 保存失败资源列表:"))
		for _, v := range cr.SE {
			ws.Write([]byte(v))
		}

		// 创建最终返回结果
		ws.Write([]byte(`{"preurl":"` + cr.PreUrl + `", "zipurl":"` + cr.ZipUrl + `", "pid":"` + cr.Pid + `"}`))
		ws.Write([]byte("end")) // 输出结束信号
		<-maxsearch             // 完成本次抓取操作，释放占用的链接数量

	}
	fmt.Println("<-- sendRecvServer finished")
}

// 查询PersistentId对应的压缩队列执行状态
func PersistentId(w http.ResponseWriter, r *http.Request) {
	pid := r.FormValue("pid")
	resp, err := http.Get("http://api.qiniu.com/status/get/prefop?id=" + pid)
	if err != nil {
		w.Write([]byte(`{"code":1, "message": "服务器请求异常，请稍后再试"}`))
		return
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		w.Write([]byte(`{"code":1, "message": "服务器请求异常，请稍后再试"}`))
		return
	}
	defer resp.Body.Close()

	rt := make(map[string]interface{})
	err = json.Unmarshal(body, &rt)
	if err != nil {
		w.Write([]byte(`{"code":1, "message": "服务器请求异常，请稍后再试"}`))
		return
	}

	var ms string
	fmt.Println(rt["code"])
	switch rt["code"].(float64) {
	case 0:
		ms = `{"code":0}`
	case 1:
		ms = `{"code":1, "message": "压缩队列等待处理中。。。 请稍后再进行获取"}`
	case 2:
		ms = `{"code":2, "message": "压缩队列正在处理中。。。 请稍后再进行获取"}`
	case 3:
		ms = `{"code":3, "message": "压缩处理失败，请重新抓取！对此我们感到非常抱歉"}`
	case 4:
		ms = `{"code":4, "message": "压缩队列通知提交失败，请重新抓取！对此我们感到非常抱歉"}`
	default:
		ms = `{"code":5, "message": "压缩队列未知异常，请重新抓取！对此我们感到非常抱歉"}`
	}
	w.Write([]byte(ms))
}

// 记录抓取结果日志信息
func SL(cr core.CopyerResult) {

}
